추천 기능 구현 및 모듈 이전으로 인한 수정을 진행합니다.#340
Conversation
피처 예시 앱이 앱 레이어(MLSAppFeatureInterface)를 의존하는 문제를 해결. LoginExitRoute를 MLSCore로 이동하고 관련 타깃 의존성을 정리.
- BookmarkRepository(MLSBookmarkFeatureInterface)를 사용해 북마크 추가/삭제 처리 - 북마크 토글 후 셀 UI 즉시 반영 (distinctUntilChanged mapId+bookmarkId 비교) - 북마크 추가/삭제 시 스낵바 표시, 컬렉션 추가 및 되돌리기 지원 - 셀 탭 시 상세 화면(DictionaryDetail)으로 이동 - 예시 앱에 Mock 의존성 및 클로저 주입 추가
BottomTabBarController가 각 탭의 NavigationController delegate로 등록되어 스택 depth를 감지해 자동으로 탭바 표시/숨김 처리.
UIImage(named:) -> DesignSystemAsset.image(named:)로 변경하여 SPM 모듈 번들에서 이미지를 올바르게 로드하도록 수정. 탭바 양옆 투명 영역에 배경 뷰 추가.
앱 시작 시 App Store 버전과 비교하여 강제/선택 업데이트 얼럿 표시. 강제 업데이트는 포그라운드 복귀 시 얼럿 재표시, URL 열기 실패 시에도 재표시.
There was a problem hiding this comment.
Code Review
This pull request introduces an app update checker feature and integrates bookmarking capabilities (adding, deleting, and undoing bookmarks with snackbar notifications) into the recommendation feature. It also refactors the custom bottom tab bar controller to dynamically hide or show itself based on navigation depth. The review feedback highlights several key areas for improvement: preventing potential memory leaks in the update observer, resolving potential delegate conflicts on the navigation controller, ensuring consistent tab bar transition animations, preventing duplicate API requests from rapid bookmark toggling, and simplifying the reactive UI event binding stream.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| case .force: | ||
| showForceUpdateAlert() | ||
| forceUpdateObserver = NotificationCenter.default.addObserver( | ||
| forName: UIApplication.didBecomeActiveNotification, | ||
| object: nil, | ||
| queue: .main | ||
| ) { [weak self] _ in | ||
| self?.showForceUpdateAlert() | ||
| } |
There was a problem hiding this comment.
NotificationCenter의 블록 기반 addObserver는 반환된 옵저버 토큰을 명시적으로 제거하지 않으면 메모리 누수가 발생할 수 있습니다. AppLauncher가 해제되거나 새로운 옵저버를 등록하기 전에 기존 옵저버를 NotificationCenter.default.removeObserver를 통해 제거해주는 것이 안전합니다.
case .force:
showForceUpdateAlert()
if let existingObserver = forceUpdateObserver {
NotificationCenter.default.removeObserver(existingObserver)
}
forceUpdateObserver = NotificationCenter.default.addObserver(
forName: UIApplication.didBecomeActiveNotification,
object: nil,
queue: .main
) { [weak self] _ in
self?.showForceUpdateAlert()
}| let nav: UINavigationController | ||
| if let existing = $0 as? UINavigationController { | ||
| nav = existing | ||
| } else { | ||
| return UINavigationController(rootViewController: $0) | ||
| nav = UINavigationController(rootViewController: $0) | ||
| } | ||
| nav.delegate = self | ||
| return nav | ||
| } |
| func handleToggleBookmark(mapId: Int) -> Observable<Mutation> { | ||
| guard let map = currentState.recommendations.first(where: { $0.mapId == mapId }) else { | ||
| return .empty() | ||
| } | ||
|
|
||
| if let bookmarkId = map.bookmarkId { | ||
| return bookmarkRepository.deleteBookmark(bookmarkId: bookmarkId) | ||
| .flatMap { _ -> Observable<Mutation> in | ||
| .from([ | ||
| .setLastDeleted(map), | ||
| .updateBookmarkId(mapId: mapId, bookmarkId: nil), | ||
| .setUIEvent(.deleted(map)) | ||
| ]) | ||
| } | ||
| .catch { _ in .empty() } | ||
| } else { | ||
| return bookmarkRepository.setBookmark(resourceId: mapId, type: .map) | ||
| .flatMap { newBookmarkId -> Observable<Mutation> in | ||
| let updated = RecommendationMap( | ||
| mapId: map.mapId, score: map.score, | ||
| iconUrl: map.iconUrl, nameKr: map.nameKr, | ||
| bookmarkId: newBookmarkId | ||
| ) | ||
| return .from([ | ||
| .updateBookmarkId(mapId: mapId, bookmarkId: newBookmarkId), | ||
| .setUIEvent(.added(updated)) | ||
| ]) | ||
| } | ||
| .catch { _ in .empty() } | ||
| } | ||
| } |
|
고생하셨습니다!
|
|
@pinocchio22 |
📌 이슈
✅ 작업 사항
추천 기능 구현
ToLoginView) 및 수정하기 버튼 → 캐릭터 설정 화면 이동BookmarkRepository재사용distinctUntilChangedmapId + bookmarkId 비교)탭바 개선
UINavigationControllerDelegate활용)버그 수정
AppCoordinator타입 불일치 수정 (AppCoordinator→AppCoordinatorProtocol)MLSDesignSystemSPM 모듈 내UIImage(named:)→DesignSystemAsset.image(named:)전환 (편집 버튼 아이콘, 경고 아이콘 등 5곳)의존성 구조 개선
LoginExitRoute를MLSAppFeatureInterface→MLSCore로 이동 (피처 예시 앱의 앱 레이어 의존 제거)앱 업데이트 체크
itms-apps://)